
module("luci.controller.Ditel_ACU.MCU_Upgrade", package.seeall) --定义一个lua模块
--local log = require "luci.log"
function sleep(n)
    os.execute("sleep "..n)
end
function index()
        entry({"admin", "MCU_Upgrade"}, firstchild(), translate("MCU Configuration"), 106) 
            entry({"admin", "MCU_Upgrade", "mcu_upgrade"}, call("action_flashops") , translate("UPGRADE MCU"), 107)
                entry({"admin", "MCU_Upgrade", "mcu_upgrade","mcuupgrade"}, call("action_mcuupgrade"), nil,108)
                entry({"admin", "MCU_Upgrade", "mcu_upgrade","progress"}, call("action_progress"), nil, 108)
                entry({"admin", "MCU_Upgrade", "mcu_upgrade","openWebUserApp"}, call("action_openWebUserApp"), nil, 108)
            entry({"admin", "MCU_Upgrade", "mcu_restore"}, call("action_mcu_restore") , translate("Restore MCU"), 107)
                entry({"admin", "MCU_Upgrade", "mcu_restore", "restore"}, call("action_restore"), nil, 108)
            entry({"admin", "MCU_Upgrade", "mcu_restart"}, call("action_mcu_restart") , translate("Restart MCU"), 107)
                entry({"admin", "MCU_Upgrade", "mcu_restart", "restart"}, call("action_restart"), nil, 108)
end


--调用MCU恢复出厂设置
function action_mcu_restore()

    luci.template.render("ACU_Restore/restore_mcu", {
        restore_success = false
    })
end
--执行MCU恢复出厂设置功能
function action_restore()

    local input_file = "/etc/config/WEB/Restore/RestoreInput"
    local output_file = "/etc/config/WEB/Restore/RestoreOutput"
    if nixio.fs.access(input_file)
    then 
        
        nixio.fs.writefile(input_file, "$GCCMD,RESTORE MCU*FF\r\n")
        action_mcu_restore()
    else
        luci.http.write("Error: open ".. input_file .. "failed\n")
    end
end


--调用重启MCU界面
function action_mcu_restart()

    luci.template.render("ACU_Restart/restart_mcu", {
        restart_success = false
    })
end

--执行MCU重启功能
function action_restart()

    local input_file = "/etc/config/WEB/Restart/RestartInput"
    local output_file = "/etc/config/WEB/Restart/RestartOutput"
    if nixio.fs.access(input_file)
    then 
        
        nixio.fs.writefile(input_file, "$GCCMD,RESTART MCU*FF\r\n")
        action_mcu_restart()
    else
        luci.http.write("Error: open ".. input_file .. "failed\n")
    end
end

--判断升级文件是否合法
local function image_supported(image)
    --判断是否为bin文件
    --升级的BIN文件头4个字节应该为 XX XX 00 20
    local buff = {0}
    if nixio.fs.access(image)
    then
        local str = nixio.fs.readfile(image, 4)

        for i = 1,string.len(str),1 do
            buff[i] = string.byte(string.sub(str, i , i))
        end
        if (buff[3] == 0 and buff[4] == 32)
        then
            return 1
        end
    end
    return nil
end
--计算md5sum
local function image_checksum(image)
    return (luci.sys.exec("md5sum %q" % image):match("^([^%s]+)"))
end
--计算sha256sum
local function image_sha256_checksum(image)
    return (luci.sys.exec("sha256sum %q" % image):match("^([^%s]+)"))
end

local function storage_size()
    local size = 0
    if nixio.fs.access("/proc/mtd") then
        for l in io.lines("/proc/mtd") do
            local d, s, e, n = l:match('^([^%s]+)%s+([^%s]+)%s+([^%s]+)%s+"([^%s]+)"')
            if n == "linux" or n == "firmware" then
                size = tonumber(s, 16)
                break
            end
        end
    elseif nixio.fs.access("/proc/partitions") then
        for l in io.lines("/proc/partitions") do
            local x, y, b, n = l:match('^%s*(%d+)%s+(%d+)%s+([^%s]+)%s+([^%s]+)')
            if b and n and not n:match('[0-9]') then
                size = tonumber(b) * 1024
                break
            end
        end
    end
    return size
end
--升级MCU
function action_flashops()
    --
    -- Overview
    --
    luci.template.render("ACU_upgrade/upload", {
        upgrade_avail = true
    })
end



function action_mcuupgrade()
    local fs = require "nixio.fs"
    local http = require "luci.http"
    local jsonc = require "luci.jsonc"
    local image_tmp = "/tmp/upgrade.bin"

    --将文件上传到/tmp/upgrade.bin
    local fp
    http.setfilehandler(
        function(meta, chunk, eof)
            if not fp and meta and meta.name == "image" then
                fp = io.open(image_tmp, "w")
            end
            if fp and chunk then
                fp:write(chunk)
            end
            if fp and eof then
                fp:close()
            end
        end
    )

    if not luci.dispatcher.test_post_security() then
        fs.unlink(image_tmp)
        return
    end

    --
    -- Cancel firmware flash
    --
    if http.formvalue("cancel") then
        fs.unlink(image_tmp)
        http.redirect(luci.dispatcher.build_url('admin/MCU_Upgrade/mcu_upgrade'))
        return
    end

    --
    -- Initiate firmware flash
    --
    local step = tonumber(http.formvalue("step") or 1)
    if step == 1 then
        --调用确认升级操作页面
        if image_supported(image_tmp) == 1 then
            luci.template.render("ACU_upgrade/upload_confirm", {
                checksum = image_checksum(image_tmp),
                sha256ch = image_sha256_checksum(image_tmp),
                storage  = storage_size(),
                size     = (fs.stat(image_tmp, "size") or 0),
                --keep     = (not not http.formvalue("keep"))
            })
        else
        --提示文件格式错误，并且删除文件
            fs.unlink(image_tmp)
            luci.template.render("ACU_upgrade/upload", {
                upgrade_avail = true,
                image_invalid = true
            })
        end
    --
    -- Start sysupgrade flash
    --
    elseif step == 2 then
        luci.template.render("ACU_upgrade/finish", {
            title = luci.i18n.translate("Flashing..."),
            msg   = luci.i18n.translate("The MCU is flashing now.<br /> DO NOT POWER OFF THE DEVICE!<br /> Wait about 3 minutes then reboot ACU ."),
        })
        --关闭WebUserApp
        luci.sys.exec("killall WebUserApp >/dev/null")
        --运行升级MCU程序
        luci.sys.exec("UpgradeMcuApp -f /tmp/upgrade.bin -s 500 > /dev/null")
    end
end
--获取当前更新进度
function action_progress()
    local str = ""
    local filename = "/etc/config/WEB/Upgrade/upgrade_progress"
    if nixio.fs.access(filename)
    then
        str = nixio.fs.readfile(filename, 10)
        luci.http.write(str)	
    end
end
--开启WebUserApp
function action_openWebUserApp()
    luci.sys.exec("WebUserApp >/dev/null")
end
